/**
 * 神奇九转TD序列监控服务
 * 基于汤姆·迪马克(Tom Demark)的TD序列指标
 */
const axios = require('axios');
const moment = require('moment');
const logger = require('./logger');
const config = require('../config');

// 企业微信机器人配置
const WECOM_WEBHOOKS = [
    'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=ce7e2d90-ba33-496a-bfc6-09fa0a74b47a'
];

// 自定义日志函数，打印CST时间
function logWithCstTime(message) {
    const now = new Date();
    // 将UTC时间转换为CST时间（+8小时）
    const cstTime = new Date(now.getTime() + 8 * 60 * 60 * 1000);
    const timeString = cstTime.toISOString().replace('T', ' ').replace('Z', '');
    console.log(`[${timeString} CST] ${message}`);
}

/**
 * 获取K线数据
 * @param {string} symbol - 交易对
 * @param {string} interval - 时间间隔
 * @param {number} limit - 获取数量
 * @returns {Promise<Array>} K线数据数组
 */
async function getKlines(symbol, interval, limit) {
    try {
        // 确保limit是一个有效的数字
        const validLimit = typeof limit === 'number' && !isNaN(limit) ? limit : 60;
        
        logWithCstTime(`开始获取币安K线数据: ${symbol} ${interval} limit=${validLimit}`);
        
        const response = await axios.get('https://api.binance.com/api/v3/klines', {
            params: {
                symbol: symbol,
                interval: interval,
                limit: validLimit
            },
            headers: {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
            }
        });
        
        if (!response.data || !Array.isArray(response.data) || response.data.length === 0) {
            logWithCstTime(`获取K线数据失败，响应数据为空或无效: ${JSON.stringify(response.data)}`);
            return null;
        }
        
        logWithCstTime(`成功获取${response.data.length}条K线数据`);
        
        // 转换数据格式
        const klines = response.data.map(k => ({
            open_time: new Date(parseInt(k[0])),
            open_price: parseFloat(k[1]),
            high_price: parseFloat(k[2]),
            low_price: parseFloat(k[3]),
            close_price: parseFloat(k[4]),
            volume: parseFloat(k[5]),
            close_time: new Date(parseInt(k[6]))
        }));
        
        // 按时间排序，最新的在后面
        klines.sort((a, b) => a.open_time.getTime() - b.open_time.getTime());
        
        return klines;
    } catch (error) {
        logWithCstTime(`获取K线数据出错: ${error.message}`);
        return null;
    }
}

/**
 * 计算TD序列 - 根据TradingView的TD指标代码优化
 * @param {Array} klines - K线数据数组
 * @returns {Object} 包含买入和卖出TD序列的对象
 */
function calculateTDSequence(klines) {
    if (!klines || klines.length < 5) {
        return { buySetup: [], sellSetup: [] };
    }
    
    // 初始化TD序列计数数组
    const tdUp = Array(klines.length).fill(0);  // 上涨九转计数
    const tdDown = Array(klines.length).fill(0); // 下跌九转计数
    
    // 从第5根K线开始计算（需要用到4天前的收盘价）
    for (let i = 4; i < klines.length; i++) {
        const currentClose = klines[i].close_price;
        const fourBarsBackClose = klines[i - 4].close_price;
        
        // 按照TV的逻辑计算TD序列
        // TD = close > close[4] ?nz(TD[1])+1:0
        // TS = close < close[4] ?nz(TS[1])+1:0
        if (currentClose > fourBarsBackClose) {
            tdUp[i] = tdUp[i-1] + 1;  // 连续计数+1
        } else {
            tdUp[i] = 0;  // 重置计数
        }
        
        if (currentClose < fourBarsBackClose) {
            tdDown[i] = tdDown[i-1] + 1;  // 连续计数+1
        } else {
            tdDown[i] = 0;  // 重置计数
        }
    }
    
    // 找出买入信号（下跌九转）
    const buySetup = [];
    for (let i = 4; i < klines.length; i++) {
        if (tdDown[i] >= 9 && tdDown[i-1] < 9) {
            // 刚刚形成第9根，形成完整的下跌九转
            // 收集九转形成过程中的所有K线
            const sequenceKlines = [];
            let totalPercentChange = 0;
            
            for (let j = 0; j < 9; j++) {
                const klineIndex = i - j;
                if (klineIndex >= 4) {
                    const k = klines[klineIndex];
                    const fourBarsBackClose = klines[klineIndex - 4].close_price;
                    const percentChange = ((k.close_price - fourBarsBackClose) / fourBarsBackClose * 100);
                    
                    sequenceKlines.push({
                        kline: k,
                        fourBarsBackClose: fourBarsBackClose,
                        percentChange: percentChange
                    });
                    
                    totalPercentChange += percentChange;
                }
            }
            
            // 按时间排序
            sequenceKlines.sort((a, b) => a.kline.open_time.getTime() - b.kline.open_time.getTime());
            
            buySetup.push({
                index: i,
                kline: klines[i],
                count: 9,
                completed: true,
                sequenceKlines: sequenceKlines,
                avgPercentChange: totalPercentChange / sequenceKlines.length
            });
        }
    }
    
    // 找出卖出信号（上涨九转）
    const sellSetup = [];
    for (let i = 4; i < klines.length; i++) {
        if (tdUp[i] >= 9 && tdUp[i-1] < 9) {
            // 刚刚形成第9根，形成完整的上涨九转
            // 收集九转形成过程中的所有K线
            const sequenceKlines = [];
            let totalPercentChange = 0;
            
            for (let j = 0; j < 9; j++) {
                const klineIndex = i - j;
                if (klineIndex >= 4) {
                    const k = klines[klineIndex];
                    const fourBarsBackClose = klines[klineIndex - 4].close_price;
                    const percentChange = ((k.close_price - fourBarsBackClose) / fourBarsBackClose * 100);
                    
                    sequenceKlines.push({
                        kline: k,
                        fourBarsBackClose: fourBarsBackClose,
                        percentChange: percentChange
                    });
                    
                    totalPercentChange += percentChange;
                }
            }
            
            // 按时间排序
            sequenceKlines.sort((a, b) => a.kline.open_time.getTime() - b.kline.open_time.getTime());
            
            sellSetup.push({
                index: i,
                kline: klines[i],
                count: 9,
                completed: true,
                sequenceKlines: sequenceKlines,
                avgPercentChange: totalPercentChange / sequenceKlines.length
            });
        }
    }
    
    return { buySetup, sellSetup };
}

/**
 * 检查是否应该发送通知
 * @param {Object} sequence - TD序列对象
 * @param {Map} lastAlerts - 上次提醒记录
 * @returns {Object|null} 通知信息或null
 */
function checkForAlerts(sequence, symbol, interval, lastAlerts) {
    const { buySetup, sellSetup } = sequence;
    let alertsToSend = [];
    
    // 检查买入序列（下跌9结构）
    buySetup.forEach(setup => {
        if (setup.completed) {
            const alertKey = `${symbol}-${interval}-buy-${setup.kline.open_time.getTime()}`;
            if (!lastAlerts.has(alertKey)) {
                // 构建K线详情
                const klineDetails = setup.sequenceKlines.map((item, index) => ({
                    index: 9 - index, // 倒序编号，最后一根为9
                    time: item.kline.open_time,
                    close: item.kline.close_price,
                    fourBarsBackClose: item.fourBarsBackClose,
                    percentChange: item.percentChange.toFixed(2) + '%'
                }));
                
                alertsToSend.push({
                    type: 'buy',
                    symbol,
                    interval,
                    time: setup.kline.open_time,
                    price: setup.kline.close_price,
                    key: alertKey,
                    sequenceDetails: {
                        count: setup.count,
                        avgPercentChange: setup.avgPercentChange.toFixed(2) + '%',
                        klineDetails: klineDetails
                    }
                });
            }
        }
    });
    
    // 检查卖出序列（上涨9结构）
    sellSetup.forEach(setup => {
        if (setup.completed) {
            const alertKey = `${symbol}-${interval}-sell-${setup.kline.open_time.getTime()}`;
            if (!lastAlerts.has(alertKey)) {
                // 构建K线详情
                const klineDetails = setup.sequenceKlines.map((item, index) => ({
                    index: 9 - index, // 倒序编号，最后一根为9
                    time: item.kline.open_time,
                    close: item.kline.close_price,
                    fourBarsBackClose: item.fourBarsBackClose,
                    percentChange: item.percentChange.toFixed(2) + '%'
                }));
                
                alertsToSend.push({
                    type: 'sell',
                    symbol,
                    interval,
                    time: setup.kline.open_time,
                    price: setup.kline.close_price,
                    key: alertKey,
                    sequenceDetails: {
                        count: setup.count,
                        avgPercentChange: setup.avgPercentChange.toFixed(2) + '%',
                        klineDetails: klineDetails
                    }
                });
            }
        }
    });
    
    return alertsToSend.length > 0 ? alertsToSend : null;
}

/**
 * 发送企业微信通知
 * @param {Array} alerts - 需要发送的预警信息数组
 */
async function sendWeComNotification(alerts) {
    if (!alerts || alerts.length === 0) {
        return;
    }
    
    for (const alert of alerts) {
        try {
            const { type, symbol, interval, time, price, sequenceDetails } = alert;
            // 格式化时间（转换为本地时间，格式：YYYY-MM-DD HH:mm:ss）
            const formattedTime = moment(time).format('YYYY-MM-DD HH:mm:ss');
            
            // 信号类型文字
            const signalType = type === 'buy' ? '下跌九转结构形成' : '上涨九转结构形成';
            // 信号含义
            const signalMeaning = type === 'buy' ? '可能见底反弹，考虑逢低买入' : '可能顶部回落，考虑逢高卖出';
            // 信号颜色
            const signalColor = type === 'buy' ? '🔴' : '🟢';
            
            // 计算每根K线的详细信息
            const klineDetailsText = sequenceDetails.klineDetails
                .sort((a, b) => b.index - a.index) // 按序号倒序排列，9号排在最前面
                .map(k => {
                    const timeStr = moment(k.time).format('MM-DD HH:mm');
                    return `${k.index}. ${timeStr} 收盘价: ${k.close} vs 4根前: ${k.fourBarsBackClose} (${k.percentChange})`;
                })
                .join('\n');
            
            // 构建通知消息
            const message = `${signalColor} ${symbol} ${interval} ${signalType}

📊 交易对: ${symbol}
⏱️ 时间周期: ${interval}
🕒 形成时间: ${formattedTime}
💰 当前价格: ${price}

📈 信号含义: ${signalMeaning}

🔍 判断依据:
连续9根K线的收盘价均${type === 'buy' ? '低于' : '高于'}各自4根K线之前的收盘价

📊 九转形成过程 (平均变化: ${sequenceDetails.avgPercentChange}):
${klineDetailsText}

📝 使用建议:
• ${type === 'buy' ? '下跌' : '上涨'}九转信号出现后，通常意味着${type === 'buy' ? '下跌' : '上涨'}趋势可能已经${type === 'buy' ? '筑底' : '见顶'}
• 可以考虑${type === 'buy' ? '分批建仓' : '逐步减仓'}，而不是一次性${type === 'buy' ? '满仓' : '清仓'}
• 建议和其他技术指标（如RSI、MACD）配合判断
• ${type === 'buy' ? '大熊' : '大牛'}市中可能出现连续多个九转信号

📊 历史表现:
根据统计分析，TD序列在震荡市场中的准确率较高，而在单边强趋势中的作用会减弱

📚 神奇九转指标解析:
TD序列（神奇九转）是由技术分析大师汤姆·迪马克(Tom Demark)创立的指标，专门用于识别市场的可能转折点。
当价格形成完整的九转结构后，反转概率增大，但并非100%准确，需要结合市场环境和其他指标综合判断。

🔗 查看图表: https://www.tradingview.com/chart/?symbol=BINANCE:${symbol}&interval=${interval}

💡 注意: 本消息仅供参考，不构成投资建议，请谨慎决策。`;

            // 判断是否是测试模式
            const isTestMode = process.argv.includes('test');
            const finalMessage = isTestMode ? `[测试消息] ${message}` : message;
            
            // 企业微信推送
            let success = false;
            let error = null;
            
            // 尝试每个webhook
            for (const webhook of WECOM_WEBHOOKS) {
                try {
                    const response = await axios.post(webhook, {
                        msgtype: 'text',
                        text: {
                            content: finalMessage
                        }
                    });
                    
                    if (response.data && response.data.errcode === 0) {
                        success = true;
                        logWithCstTime(`成功发送${type === 'buy' ? '买入' : '卖出'}信号通知: ${symbol} ${interval}`);
                        break; // 发送成功，跳出循环
                    } else {
                        error = `企业微信返回错误: ${JSON.stringify(response.data)}`;
                    }
                } catch (err) {
                    error = err.message;
                    // 继续尝试下一个webhook
                }
            }
            
            if (!success) {
                logWithCstTime(`发送通知失败: ${error}`);
            }
        } catch (error) {
            logWithCstTime(`处理通知时出错: ${error.message}`);
        }
    }
}

/**
 * 运行TD序列监控任务
 * @param {string} symbol - 交易对
 * @param {string} interval - 时间间隔
 * @param {Map} lastAlerts - 上次提醒记录，用于避免重复提醒
 */
async function monitorTDSequence(symbol, interval, lastAlerts) {
    try {
        // 获取K线数据
        const klines = await getKlines(symbol, interval, 50);
        
        if (!klines || klines.length < 5) {
            logWithCstTime(`获取K线数据不足，无法计算TD序列`);
            return;
        }
        
        // 计算TD序列
        const sequence = calculateTDSequence(klines);
        
        // 检查是否需要发送提醒
        const alerts = checkForAlerts(sequence, symbol, interval, lastAlerts);
        
        // 如果有需要发送的提醒
        if (alerts && alerts.length > 0) {
            await sendWeComNotification(alerts);
            
            // 更新提醒记录
            alerts.forEach(alert => {
                lastAlerts.set(alert.key, Date.now());
            });
            
            logWithCstTime(`已发送${alerts.length}条TD序列提醒`);
        } else {
            logWithCstTime(`没有新的TD序列提醒 ${symbol} ${interval}`);
        }
    } catch (error) {
        logWithCstTime(`TD序列监控任务出错: ${error.message}`);
    }
}

/**
 * 启动TD序列监控
 * @param {Array} symbols - 要监控的交易对数组
 * @param {Array} intervals - 要监控的时间间隔数组
 */
function startTDSequenceMonitor(symbols = ['BTCUSDT', 'ETHUSDT'], intervals = ['15m', '1h', '4h', '1d']) {
    const lastAlerts = new Map();
    
    logWithCstTime('启动TD序列监控服务...');
    logWithCstTime(`监控交易对: ${symbols.join(', ')}`);
    logWithCstTime(`监控时间周期: ${intervals.join(', ')}`);
    
    // 立即执行一次
    runTDSequenceTasks();
    
    // 每10分钟执行一次
    setInterval(runTDSequenceTasks, 10 * 60 * 1000);
    
    // 内部函数，运行所有监控任务
    async function runTDSequenceTasks() {
        logWithCstTime('执行TD序列监控任务...');
        
        for (const symbol of symbols) {
            for (const interval of intervals) {
                try {
                    await monitorTDSequence(symbol, interval, lastAlerts);
                } catch (error) {
                    logWithCstTime(`执行TD序列监控任务出错: ${symbol} ${interval}, ${error.message}`);
                }
            }
        }
    }
}

module.exports = {
    startTDSequenceMonitor,
    monitorTDSequence,
    calculateTDSequence,
    getKlines
}; 